/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package session.stateful;

import entity.StakeholderEntity;
import entity.GrouponEntity;
import entity.PaymentItemEntity;
import entity.IssuedGrouponEntity;
import entity.PurchasedGrouponEntity;
import entity.GrouponPaymentItemEntity;
import entity.TouristAccountEntity;
import entity.TransactionsEntity;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Date;
import java.sql.Time;
import java.util.List;
import java.util.ArrayList;
import javax.ejb.LocalBean;
import javax.ejb.Stateful;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
// Additional imports
import java.math.BigInteger;
import javax.ejb.EJB;
import util.entityhelper.GrouponHelper;
// Import for the payment and refund
import com.paypal.sdk.core.nvp.NVPDecoder;
import com.paypal.sdk.core.nvp.NVPEncoder;
import com.paypal.sdk.profiles.APIProfile;
import com.paypal.sdk.profiles.ProfileFactory;
import com.paypal.sdk.services.NVPCallerServices;
import java.util.Random;

/**
 *
 * @author NGUYEN CONG DAT
 */
@Stateful
@LocalBean
public class GrouponSessionBean {

    @PersistenceContext
    private EntityManager entityManager;
    @EJB
    private EmailSessionBean emailSessionBean;
    private static final String AB = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static Random rnd = new Random();

    public GrouponSessionBean() {
        emailSessionBean = new EmailSessionBean();
        emailSessionBean.setUser("is3102team32@gmail.com");
        emailSessionBean.setPassword("emsongtronguocao");
    }

    public void createGroupon(Long stakeholderId, GrouponEntity groupon) {
        groupon.setStatus("Application Pending");
        groupon.setDateOfSubmission(new Date());
        System.out.println("createGroupon: " + groupon.getImageURL());

        entityManager.persist(groupon);
        StakeholderEntity stakeholder = entityManager.find(StakeholderEntity.class, stakeholderId);
        stakeholder.getGroupons().add(groupon);
        groupon.setStakeholder(stakeholder);
    }

    public void editGroupon(GrouponEntity groupon) {
        entityManager.merge(groupon);
    }

    public void voidGrouponApplication(Long grouponId) {
        GrouponEntity groupon = entityManager.find(GrouponEntity.class, grouponId);
        StakeholderEntity stakeholder = groupon.getStakeholder();
        List<GrouponEntity> groupons = stakeholder.getGroupons();
        groupons.remove(groupon);
        entityManager.remove(groupon);
        entityManager.merge(stakeholder);
    }

    public void declareVoucherAsUsed(Long voucherId) {
        IssuedGrouponEntity voucher = entityManager.find(IssuedGrouponEntity.class, voucherId);
        voucher.setDateOfUsage(new Date());
        voucher.setUsed(true);
        entityManager.merge(voucher);
    }
    
    public List<IssuedGrouponEntity> getVoucherByReferenceNumber(String referenceNumber) {
        Query query = entityManager.createQuery("SELECT i FROM IssuedGrouponEntity i WHERE i.referenceNumber = :referenceNumber");
        query.setParameter("referenceNumber", referenceNumber);
        return query.getResultList();
    }
    
    public void makeGrouponOrder(Long grouponId, Long touristId, PurchasedGrouponEntity purchasedGroupon) {
        GrouponEntity groupon = entityManager.find(GrouponEntity.class, grouponId);
        TouristAccountEntity tourist = entityManager.find(TouristAccountEntity.class, touristId);
        purchasedGroupon.setStatus("Not Paid");
        purchasedGroupon.setTourist(tourist);
        purchasedGroupon.setGroupon(groupon);
        entityManager.persist(purchasedGroupon);
        tourist.getPurchasedGroupons().add(purchasedGroupon);
        groupon.getPurchasedGroupons().add(purchasedGroupon);
        if (getQuantityBought(groupon.getId()) >= groupon.getMaximumIssuedQuantity()) {
            groupon.setStatus("Deal is over");
            List<PurchasedGrouponEntity> purchasedGroupons = groupon.getPurchasedGroupons();
            // Issue groupons to successful tourists
            generateIssuedGroupons(groupon.getStakeholder().getId(), groupon.getId());
            for (int j = 0; j < purchasedGroupons.size(); j++) {
                PurchasedGrouponEntity temp = purchasedGroupons.get(j);
                // Send an email to tourist, informing payment has been settled and attaching the groupons for them
                System.out.println("before call send email method");
                sendEmailToSuccessfulGrouponPurchaseTourists(temp.getId());
            }
        }
    }

    private void sendEmailToSuccessfulGrouponPurchaseTourists(Long purchasedGrouponId) {
        try {
            PurchasedGrouponEntity purchasedGroupon = entityManager.find(PurchasedGrouponEntity.class, purchasedGrouponId);
            String grouponList = "";
            for (int i = 0; i < purchasedGroupon.getQuantity(); i++) {
                grouponList = grouponList + "Groupon " + (i + 1) + " : " + purchasedGroupon.getIssuedGroupons().get(i).getReferenceNumber() + "\n";
            }
            String message = "Dear" + purchasedGroupon.getTourist().getTourist().getFirstName() + " " + purchasedGroupon.getTourist().getTourist().getLastName()
                    + ", \n\nThank you for purchasing on FoodSage.sg.\n\n"
                    + "This is to inform you that your groupon purchase on FoodSage.sg has been successful \n"
                    + "Here is your purchase details: \n"
                    + "Purchase reference number: " + purchasedGroupon.getConfirmationId() + "\n"
                    + "Groupon name: " + purchasedGroupon.getGroupon().getName() + "\n"
                    + "Groupon confirmation IDs :" + "\n"
                    + grouponList + "\n"
                    + "Remember that your groupon(s) will be valid from " + purchasedGroupon.getGroupon().getStartValidDate() + " to " + purchasedGroupon.getGroupon().getEndValidDate() + ".\n"
                    + "Also, don't forget to visit our website to enjoy many other great deals and promotions offered.\n"
                    + "Have a nice day. \n\n FoodSage.sg. ";
            emailSessionBean.setUser("is3102team32@gmail.com");
            emailSessionBean.setPassword("emsongtronguocao");
            emailSessionBean.sendMail("is3102team32@gmail.com", purchasedGroupon.getTourist().getTourist().getEmail(), "FoodSage.sg Groupon Purchase Reference for "
                    + purchasedGroupon.getTourist().getTourist().getFirstName() + " " + purchasedGroupon.getTourist().getTourist().getLastName(), message);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void deactivateGroupon(Long grouponId) {
        GrouponEntity groupon = entityManager.find(GrouponEntity.class, grouponId);
        groupon.setStatus("Deal is over");
        List<PurchasedGrouponEntity> purchasedGroupons = groupon.getPurchasedGroupons();
        for (int j = 0; j < purchasedGroupons.size(); j++) {
            PurchasedGrouponEntity purchasedGroupon = purchasedGroupons.get(j);
            purchasedGroupon.setStatus("Groupon was deactivated");
            entityManager.merge(purchasedGroupon);
            // Refund to tourist
            // 1. Get transaction
            refundPayPal(purchasedGroupon.getTransactions().get(0));
            // Email to them 
        }
    }

    public void refundPayPal(TransactionsEntity transaction) {
        try {
            String paypalTransactionId = null;
            String paypalCorrelationId = null;
            org.apache.log4j.BasicConfigurator.configure();

            Double amount = transaction.getPurchasedGroupon().getQuantity() * transaction.getPurchasedGroupon().getGroupon().getOfferedPrice();
            String note = "Refund for groupon purchase " + transaction.getPurchasedGroupon().getConfirmationId();

            paypalTransactionId = transaction.getPaypalTransactionId();
            NVPDecoder paypalResponse = RefundTransactionCode("Partial", paypalTransactionId, String.valueOf(amount), note);
            // ack variable
            boolean success = false;
            String response = "";
            String statusMessage = "";

            for (Object objKey : paypalResponse.getMap().keySet()) {
                System.out.println(objKey.toString() + " = " + paypalResponse.getMap().get(objKey));

                if (objKey.toString().equals("L_LONGMESSAGE0")) {
                    statusMessage = (String) paypalResponse.getMap().get(objKey);
                }

                // Ack is a success
                if (objKey.toString().equals("ACK")) {
                    response = (String) paypalResponse.getMap().get(objKey);
                    if (response.equals("Success")) {
                        success = true;
                    }
                }
                if (objKey.toString().equals("REFUNDTRANSACTIONID")) {
                    paypalTransactionId = (String) paypalResponse.getMap().get(objKey);
                }
                if (objKey.toString().equals("CORRELATIONID")) {
                    paypalCorrelationId = (String) paypalResponse.getMap().get(objKey);
                }
            }
            // transaction successful
            if (success == true) {
                // create payment record
                TransactionsEntity refundTransaction = new TransactionsEntity();
                refundTransaction.setAmount(-1 * amount);
                refundTransaction.setPaypalCorrelationId(paypalCorrelationId);
                refundTransaction.setPaypalTransactionId(paypalTransactionId);
                refundTransaction.setPurchasedGroupon(transaction.getPurchasedGroupon());
                refundTransaction.setTourist(transaction.getTourist());
                // Added by Cong Dat
                refundTransaction.setDatePaid(new Date());
                refundTransaction.setTimePaid(new Time(System.currentTimeMillis()));
                refundTransaction.setDescription(note);
                entityManager.persist(refundTransaction);
                List<TransactionsEntity> tempList = transaction.getTourist().getTransactions();
                tempList.add(refundTransaction);
                transaction.getTourist().setTransactions(tempList);
                //transactionSessionBean.createTransaction(-1*amount, "REFUND", paypalTransactionId, paypalCorrelationId, 
                //        transaction.getTourist(), transaction.getReservation(), transaction.getStakeholder(), transaction.getPaymentManagement());
                System.out.println("Refund Successful");
                // Email tourist about the refund
                String message = "Dear" + transaction.getTourist().getTourist().getFirstName() + " " + transaction.getTourist().getTourist().getLastName()
                        + ", \n\nThank you for purchasing on FoodSage.sg.\n\n"
                        + "This is to inform you that your groupon purchase on FoodSage.sg has been unsuccessful because the groupon sales were requested to close by TCube and its vendor.\n"
                        + "Therefore, the amount you paid to us has been refunded. \n"
                        + "Here is the refund detail: \n"
                        + "Purchase reference number: " + transaction.getPurchasedGroupon().getConfirmationId() + "\n"
                        + "Groupon name: " + transaction.getPurchasedGroupon().getGroupon().getName() + "\n"
                        + "We are really sorry for any inconvenience caused \n"
                        + " Meanwhile, don't forget to visit our website to enjoy many other great deals and promotions offered. "
                        + " Your participation is very important to us. \n"
                        + "Have a nice day. \n\nFoodSage.sg.";
                emailSessionBean.setUser("is3102team32@gmail.com");
                emailSessionBean.setPassword("emsongtronguocao");
                emailSessionBean.sendMail("is3102team32@gmail.com", transaction.getTourist().getTourist().getEmail(), "FoodSage.sg Groupon Purchase Refund For "
                        + transaction.getTourist().getTourist().getFirstName() + " " + transaction.getTourist().getTourist().getLastName(), message);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public NVPDecoder RefundTransactionCode(String refundType, String transactionId, String amount, String note) {
        NVPEncoder encoder = new NVPEncoder();
        NVPDecoder decoder = new NVPDecoder();
        NVPCallerServices caller = null;

        try {
            caller = new NVPCallerServices();
            APIProfile profile = ProfileFactory.createSignatureAPIProfile();
            /*
            WARNING: Do not embed plaintext credentials in your application code.
            Doing so is insecure and against best practices.
            Your API credentials must be handled securely. Please consider
            encrypting them for use in any production environment, and ensure
            that only authorized individuals may view or modify them.
             */

            // Set up your API credentials, PayPal end point, API operation and version.
            profile.setAPIUsername("web_1316757704_biz_api1.gmail.com");
            profile.setAPIPassword("1316757754");
            profile.setSignature("AFcWxV21C7fd0v3bYYYRCpSSRl31AobkBjpaOfK5wRRDT34RrVAP6RfZ");
            profile.setEnvironment("sandbox");
            profile.setSubject("");
            caller.setAPIProfile(profile);
            encoder.add("VERSION", "60.0");
            encoder.add("METHOD", "RefundTransaction");

            // Add request-specific fields to the request string.
            encoder.add("REFUNDTYPE", refundType);
            encoder.add("TRANSACTIONID", transactionId);
            if ((refundType != null) && (refundType.length() > 0) && (refundType.equalsIgnoreCase("Partial"))) {
                encoder.add("AMT", amount);
            }
            encoder.add("NOTE", note);

            // Execute the API operation and obtain the response.
            String NVPRequest = encoder.encode();
            String NVPResponse = (String) caller.call(NVPRequest);
            decoder.decode(NVPResponse);
        } catch (Exception ex) {

            ex.printStackTrace();
        }
        return decoder;
    }

    public List<GrouponEntity> getAllGrouponApplications() {
        List<GrouponEntity> grouponApplication = new ArrayList<GrouponEntity>();
        List<GrouponEntity> allGroupons = this.getAllGroupons();
        for (GrouponEntity obj : allGroupons) {
            if (obj.getStatus().indexOf("Application") != -1) {
                grouponApplication.add(obj);
            }
        }
        return grouponApplication;
    }

    public List<GrouponEntity> getAllGrouponApplicationsByStakeholderId(Long stakeholderId) {
        StakeholderEntity stakeholder = entityManager.find(StakeholderEntity.class, stakeholderId);
        List<GrouponEntity> allGroupons = stakeholder.getGroupons();
        List<GrouponEntity> grouponApplication = new ArrayList<GrouponEntity>();
        for (GrouponEntity obj : allGroupons) {
            if (obj.getStatus().indexOf("Application") != -1) {
                grouponApplication.add(obj);
            }
        }
        return grouponApplication;
    }

    public List<GrouponEntity> getAllPendingGrouponApplications() {
        List<GrouponEntity> pendingApplication = new ArrayList<GrouponEntity>();
        List<GrouponEntity> allGroupons = this.getAllGroupons();
        for (GrouponEntity obj : allGroupons) {
            if (obj.getStatus().equalsIgnoreCase("Application Pending")) {
                pendingApplication.add(obj);
            }
        }
        return pendingApplication;
    }

    public List<GrouponEntity> getAllPendingGrouponApplicationsByStakeholderId(Long stakeholderId) {
        StakeholderEntity stakeholder = entityManager.find(StakeholderEntity.class, stakeholderId);
        List<GrouponEntity> pendingApplication = new ArrayList<GrouponEntity>();
        List<GrouponEntity> allGroupons = stakeholder.getGroupons();
        for (GrouponEntity obj : allGroupons) {
            if (obj.getStatus().equalsIgnoreCase("Application Pending")) {
                pendingApplication.add(obj);
            }
        }
        return pendingApplication;
    }

    public List<GrouponEntity> getAllAcceptedGrouponApplications() {
        List<GrouponEntity> acceptedApplications = new ArrayList<GrouponEntity>();
        List<GrouponEntity> allGroupons = this.getAllGroupons();
        for (GrouponEntity obj : allGroupons) {
            if (obj.getStatus().equalsIgnoreCase("Application Successful")) {
                acceptedApplications.add(obj);
            }
        }
        return acceptedApplications;
    }

    public List<GrouponHelper> getAllCurrentlyOfferedGroupons() {
        List<GrouponHelper> currentlyOfferedGrouponList = new ArrayList<GrouponHelper>();
        List<GrouponEntity> allGroupons = this.getAllGroupons();
        for (GrouponEntity obj : allGroupons) {
            if (obj.getStatus().equalsIgnoreCase("Deal is on")) {
                System.out.println("TESTTTTTTTTTTTTTTTTTT");
                currentlyOfferedGrouponList.add(new GrouponHelper(obj, getQuantityBought(obj.getId())));
            }
        }
        return currentlyOfferedGrouponList;
    }

    public List<GrouponEntity> getAllCurrentlyOfferedGrouponEntities() {
        List<GrouponEntity> currentlyOfferedGrouponList = new ArrayList<GrouponEntity>();
        List<GrouponEntity> allGroupons = this.getAllGroupons();
        for (GrouponEntity obj : allGroupons) {
            if (obj.getStatus().equalsIgnoreCase("Deal is on")) {
                currentlyOfferedGrouponList.add(obj);
            }
        }
        return currentlyOfferedGrouponList;
    }

    public List<GrouponHelper> getCurrentlyOfferedGrouponsByStakeholderId(Long stakeholderId) {
        StakeholderEntity stakeholder = entityManager.find(StakeholderEntity.class, stakeholderId);
        List<GrouponEntity> allGroupons = stakeholder.getGroupons();
        List<GrouponHelper> currentlyOfferedGrouponList = new ArrayList<GrouponHelper>();
        for (GrouponEntity obj : allGroupons) {
            if (obj.getStatus().equalsIgnoreCase("Deal is on")) {
                currentlyOfferedGrouponList.add(new GrouponHelper(obj, getQuantityBought(obj.getId())));
            }
        }
        return currentlyOfferedGrouponList;
    }

    public void setStatusForGroupon(Long grouponId, String status) {
        GrouponEntity groupon = entityManager.find(GrouponEntity.class, grouponId);
        groupon.setStatus(status);
        entityManager.merge(groupon);
    }

    public List<GrouponHelper> getAllOfferedGroupons() {
        List<GrouponEntity> allGroupons = this.getAllGroupons();
        List<GrouponHelper> allOfferedGroupons = new ArrayList<GrouponHelper>();
        for (GrouponEntity obj : allGroupons) {
            if (obj.getStatus().equalsIgnoreCase("Deal is over")) {
                allOfferedGroupons.add(new GrouponHelper(obj, getQuantityBought(obj.getId())));
            }
        }
        return allOfferedGroupons;
    }

    public List<GrouponHelper> getOfferedGrouponsByStakeholderId(Long stakeholderId) {
        StakeholderEntity stakeholder = entityManager.find(StakeholderEntity.class, stakeholderId);
        List<GrouponHelper> resultList = new ArrayList<GrouponHelper>();
        List<GrouponEntity> list = stakeholder.getGroupons();
        for (GrouponEntity obj : list) {
            if (obj.getStatus().equals("Deal is over")) {
                resultList.add(new GrouponHelper(obj, getQuantityBought(obj.getId())));
            }
        }
        return resultList;
    }

    public List<GrouponEntity> getAllGroupons() {
        Query query = entityManager.createQuery("SELECT g FROM GrouponEntity g");
        return query.getResultList();
    }

    // This method is prone to error ! Be careful !!!
    public void generateIssuedGroupons(Long inputStakeholderId, Long inputGrouponId) {
        String referenceNumber = "";
        SecureRandom secureRandom = new SecureRandom();
        GrouponEntity groupon = entityManager.find(GrouponEntity.class, inputGrouponId);
        // if groupon is not null
        // What if this purchasedGroupons is null ???
        // purchasedGroupons cannot be null, this is imposed by the calling method !!!!
        List<PurchasedGrouponEntity> purchasedGroupons = groupon.getPurchasedGroupons();
        for (int i = 0; i < purchasedGroupons.size(); i++) {
            PurchasedGrouponEntity purchasedGroupon = purchasedGroupons.get(i);
            // Create a new issued groupon
            List<IssuedGrouponEntity> issuedGroupons = new ArrayList<IssuedGrouponEntity>();
            for (int j = 0; j < purchasedGroupon.getQuantity(); j++) {
                // Generate reference number for issued groupons, if the generated code is already in the database, then generate again
                while (true) {
                    referenceNumber = generateCode();
                    Query query = entityManager.createQuery("SELECT r FROM IssuedGrouponEntity r WHERE r.referenceNumber= :referenceNumber");
                    query.setParameter("referenceNumber", referenceNumber);
                    if (query.getResultList().isEmpty()) {
                        break;
                    }
                }
                IssuedGrouponEntity issuedGroupon = new IssuedGrouponEntity();
                issuedGroupon.setDateOfIssue(new Date());
                issuedGroupon.setReferenceNumber(referenceNumber);
                issuedGroupon.setPurchasedGroupon(purchasedGroupon);
                entityManager.persist(issuedGroupon);
                issuedGroupons.add(issuedGroupon);
            }
            purchasedGroupon.setIssuedGroupons(issuedGroupons);
        }
    }

    // This method supports the system in generating a unique reference number for a groupon voucher
    public String generateCode() {
        String referenceNumber = "G"; // "G" stands for Groupon
        String[] dayList = {"Q", "N", "W", "J", "D", "V", "F", "Y", "R", "3",
            "E", "O", "G", "A", "X", "I", "1", "C", "S", "M",
            "Z", "L", "U", "P", "H", "B", "T", "K", "4", "2", "5"};
        String[] monthList = {"Q", "X", "5", "Y", "A", "W", "U", "F", "7", "R", "T", "B"};
        String[] yearList = {"S", "M", "D", "H", "A", "O", "F", "N", "R", "T",
            "G", "U", "B", "I", "K", "E", "L", "P", "C", "Q",
            "Z", "Y", "X", "W", "V"};
        String[] hourList = {"G", "I", "B", "N", "O", "E", "P", "Q", "U", "W",
            "C", "X", "A", "R", "D", "H", "L", "J", "T", "V",
            "S", "F", "M"};
        Date today = new Date();
        int dayIndex = today.getDay() - 1;
        int monthIndex = today.getMonth();
        int yearIndex = today.getYear() + 1900 - 2010;
        int hourIndex = today.getHours();
        referenceNumber = referenceNumber + randomString(1) + dayList[dayIndex] + randomString(1)
                + monthList[monthIndex] + randomString(1) + yearList[(100 - yearIndex) % 25]
                + randomString(1) + hourList[hourIndex] + randomString(2);
        return referenceNumber;
    }

    private String randomString(int length) {
        StringBuilder sb = new StringBuilder(length);
        for (int i = 0; i < length; i++) {
            sb.append(AB.charAt(rnd.nextInt(AB.length())));
        }
        return sb.toString();
    }

    // This method returns the number of groupons that have been bought by tourists
    public int getQuantityBought(Long grouponId) {
        int quantity = 0;
        GrouponEntity groupon = entityManager.find(GrouponEntity.class, grouponId);
        List<PurchasedGrouponEntity> purchasedGroupons = groupon.getPurchasedGroupons();
        for (int i = 0; i < purchasedGroupons.size() && purchasedGroupons != null
                && purchasedGroupons.size() > 0; i++) {
            quantity = quantity + purchasedGroupons.get(i).getQuantity();
        }
        return quantity;
    }

    // This method returns the list of issued groupons, given the grouponId
    public List<IssuedGrouponEntity> getIssuedGroupons(Long grouponId) {
        GrouponEntity groupon = entityManager.find(GrouponEntity.class, grouponId);
        List<IssuedGrouponEntity> issuedGroupons = new ArrayList<IssuedGrouponEntity>();
        List<PurchasedGrouponEntity> purchasedGroupons = groupon.getPurchasedGroupons();
        for (int i = 0; i < purchasedGroupons.size(); i++) {
            List<IssuedGrouponEntity> temp = purchasedGroupons.get(i).getIssuedGroupons();
            for (int j = 0; j < temp.size(); j++) {
                issuedGroupons.add(temp.get(j));
            }
        }
        return issuedGroupons;
    }

    public void addGrouponPurchase(Long grouponId, Long touristId, PurchasedGrouponEntity purchasedGroupon, String paypalTransactionId, String paypalCorrelationId) {
        try {
            GrouponEntity groupon = entityManager.find(GrouponEntity.class, grouponId);
            TouristAccountEntity tourist = entityManager.find(TouristAccountEntity.class, touristId);
            TransactionsEntity transaction;
            // Generate a reference number for the booking
            purchasedGroupon.setStatus("Paid");
            purchasedGroupon.setGroupon(groupon);
            purchasedGroupon.setConfirmationId(touristId + "-" + grouponId + "-" + System.nanoTime());
            purchasedGroupon.setTourist(tourist);

            transaction = new TransactionsEntity();
            transaction.setPaypalTransactionId(paypalTransactionId);
            transaction.setPaypalCorrelationId(paypalCorrelationId);
            transaction.setTourist(tourist);
            transaction.setDatePaid(new Date());
            transaction.setAmount(purchasedGroupon.getQuantity() * groupon.getOfferedPrice());
            transaction.setPurchasedGroupon(purchasedGroupon);
            transaction.setTimePaid(new Time(System.currentTimeMillis()));
            entityManager.persist(transaction);

            List<TransactionsEntity> temp = purchasedGroupon.getTransactions();
            temp.add(transaction);
            purchasedGroupon.setTransactions(temp);
            entityManager.persist(purchasedGroupon);
            tourist.getPurchasedGroupons().add(purchasedGroupon);
            groupon.getPurchasedGroupons().add(purchasedGroupon);

            // Send an email notifying the tourist about his purchase
            String emailMessage = "Dear " + tourist.getTourist().getFirstName() + " " + tourist.getTourist().getLastName()
                    + ", \n\nThank you for purchasing on FoodSage.sg.\n\n"
                    + "This is to acknowledge that you have just had a groupon purchase on FoodSage.sg."
                    + " Your purchase reference number is " + purchasedGroupon.getConfirmationId()
                    + ".\n\nOnce the groupon is confirmed, we will send you a PDF version of the groupon(s) you have purchased."
                    + " Meanwhile, you can log in to our website to track the progress of your order, and enjoy"
                    + " many other great deals and promotions offered on FoodSage.sg. \n"
                    + "Have a nice day. \n\n FoodSage.sg. ";
            emailSessionBean.setUser("is3102team32@gmail.com");
            emailSessionBean.setPassword("emsongtronguocao");
            emailSessionBean.sendMail("is3102team32@gmail.com", tourist.getTourist().getEmail(), "FoodSage.sg Groupon Purchase Reference for "
                    + tourist.getTourist().getFirstName() + " " + tourist.getTourist().getLastName(), emailMessage);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public List<PurchasedGrouponEntity> getPurchasedGrouponsByGrouponId(Long grouponId) {
        GrouponEntity groupon = entityManager.find(GrouponEntity.class, grouponId);
        return groupon.getPurchasedGroupons();
    }
    //Method added by Khanh Vu for Web Service

    public IssuedGrouponEntity getIssuedGrouponById(long grouponId) {
        return entityManager.find(IssuedGrouponEntity.class, grouponId);
    }

    public List<IssuedGrouponEntity> getAvailIssuedGrouponByPurchasedGrouponId(long grouponId) {
        PurchasedGrouponEntity purchased = entityManager.find(PurchasedGrouponEntity.class, grouponId);

        List<IssuedGrouponEntity> list = purchased.getIssuedGroupons();

        List<IssuedGrouponEntity> result = new ArrayList<IssuedGrouponEntity>();

        for (IssuedGrouponEntity groupon : list) {
            if (!groupon.isUsed()) {
                result.add(groupon);
            }
        }
        return result;
    }

    public List<PurchasedGrouponEntity> getPurchasedGrouponByTouristId(long touristId) {
        TouristAccountEntity tourist = entityManager.find(TouristAccountEntity.class, touristId);
        return tourist.getPurchasedGroupons();
    }
    //End method added by Khanh Vu
}